<html>
    <head>
        <title>Itowns - 3D Tiles loader</title>

        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">

        <link rel="stylesheet" type="text/css" href="css/example.css">
        <link rel="stylesheet" type="text/css" href="css/LoadingScreen.css">

        <style type="text/css">
            #description {
                z-index: 2;
                left: 10px;
            }

            #featureInfoText {
                font-size: small;
            }

            #description .marg {
                margin: 10px;
            }
        </style>

        <script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.7.6/dat.gui.min.js"></script>
    </head>
    <body>
        <div id="viewerDiv"></div>
        <div id="description">Specify the URL of a tileset to load:
            <input type="text" id="url" />
            <button onclick="readURL()">Load</button>
            <div class="marg">
                <button onClick="loadLyon()">Load Lyon 1 (Mesh)</button>
                <button onClick="loadSete()">Load Sete (Point Cloud)</button>
                <button onClick="loadLille()">Load Lille (Mesh)</button>
                <div id="share"></div>
            </div>
            <hr />
            <p id="featureInfoText" class="marg"><em>Display feature information by clicking on it</em></p>
            <p><b>Feature Information:</b></p>
            <div id="featureInfo" class="marg"></div>
        </div>

        <script src="js/GUI/GuiTools.js"></script>
        <script src="../dist/itowns.js"></script>
        <script src="js/GUI/LoadingScreen.js"></script>
        <script src="../dist/debug.js"></script>

        <script type="importmap">
            {
                "imports": {
                    "three": "https://cdn.jsdelivr.net/npm/three@0.170.0/build/three.module.js",
                    "three/addons/": "https://cdn.jsdelivr.net/npm/three@0.170.0/examples/jsm/"
                }
            }
        </script>

        <script type="module">
            import {
                AmbientLight,
                PMREMGenerator,
            } from 'three';
            import { MeshoptDecoder } from 'three/addons/libs/meshopt_decoder.module.js';
            import { RoomEnvironment } from 'three/addons/environments/RoomEnvironment.js';
            import {
                zoomToLayer,
                fillHTMLWithPickingInfo,
            } from './jsm/OGC3DTilesHelper.js';

            const {
                TMSSource, WMTSSource, OGC3DTilesSource,
                ColorLayer, ElevationLayer, OGC3DTilesLayer, PNTS_SIZE_MODE,
                GlobeView, Coordinates, Fetcher,
            } = itowns;

            window.layer = null; // 3D Tiles layer

            const uri = new URL(location);

            window.gui = new dat.GUI();

            // ---- Create a GlobeView ----

            // Define camera initial position
            const placement = {
                coord: new Coordinates('EPSG:4326', 2.351323, 48.856712),
                range: 12500000,
            };

            // `viewerDiv` will contain iTowns' rendering area (`<canvas>`)
            const viewerDiv = document.getElementById('viewerDiv');

            // Create a GlobeView
            const view = new GlobeView(viewerDiv, placement, {
                controls: {
                    minDistance: 100,
                }
            });

            // Enable various compression support for 3D Tiles tileset:
            // - `KHR_draco_mesh_compression` mesh compression extension
            // - `KHR_texture_basisu` texture compression extension
            // - `EXT_meshopt_compression` data compression extension
            itowns.enableDracoLoader('./libs/draco/');
            itowns.enableKtx2Loader('./lib/basis/', view.renderer);
            itowns.enableMeshoptDecoder(MeshoptDecoder);

            // Add ambient light to globally illuminates all objects
            const light = new AmbientLight(0x404040, 40);
            view.scene.add(light);

            // Set the environment map for all physical materials in the scene.
            // Otherwise, mesh with only diffuse colors will appear black.
            const environment = new RoomEnvironment();
            const pmremGenerator = new PMREMGenerator(view.renderer);
            view.scene.environment = pmremGenerator.fromScene(environment).texture;
            pmremGenerator.dispose();

            // Setup loading screen
            setupLoadingScreen(viewerDiv, view);

            // ---- Add a basemap ----

            // Add one imagery layer to the scene. This layer's properties are
            // defined in a json file, but it cou   ld be defined as a plain js
            // object. See `Layer` documentation for more info.
            Fetcher.json('./layers/JSONLayers/OPENSM.json').then((config) => {
                const colorLayer = new ColorLayer('Ortho', {
                    ...config,
                    source: new TMSSource(config.source),
                });
                view.addLayer(colorLayer);
            });

            // ---- Add 3D terrain ----

            // Add two elevation layers: world terrain and a more precise terrain for france
            // These will deform iTowns globe geometry to represent terrain elevation.
            function addElevationLayerFromConfig(config) {
                config.source = new itowns.WMTSSource(config.source);
                var elevationLayer = new itowns.ElevationLayer(config.id, config);
                view.addLayer(elevationLayer);
            }
            itowns.Fetcher.json('./layers/JSONLayers/IGN_MNT_HIGHRES.json').then(addElevationLayerFromConfig);
            itowns.Fetcher.json('./layers/JSONLayers/WORLD_DTM.json').then(addElevationLayerFromConfig);

            // ---------- 3D Tiles loading

            function readURL() {
                const url = document.getElementById('url').value;

                if (url) {
                    setUrl(url);
                }
            }

            function setUrl(url) {
                if (!url) return;

                const input_url = document.getElementById('url');
                if (!input_url) return;

                uri.searchParams.set('copc', url);
                history.replaceState(null, null, `?${uri.searchParams.toString()}`);

                input_url.value = url;
                load(url);
            }


            function load(url) {
                const source = new OGC3DTilesSource({ url });

                if (window.layer) {
                    gui.removeFolder('Layer 3DTiles');
                    view.removeLayer('3DTiles');
                    view.notifyChange();
                    window.layer.delete();
                }

                window.layer = new OGC3DTilesLayer('3DTiles', {
                    source,
                    pntsSizeMode: PNTS_SIZE_MODE.ATTENUATED,
                });

                // Add an event for picking the 3D Tiles layer and displaying
                // information about the picked feature in an html div
                const pickingArgs = {
                    htmlDiv: document.getElementById('featureInfo'),
                    view,
                    layer: window.layer,
                };

                // Add the layer to our view
                view.addLayer(window.layer).then((layer) => {
                    zoomToLayer(view, layer);
                    window.addEventListener('click',
                        (event) => fillHTMLWithPickingInfo(event, pickingArgs), false);
                });

                window.layer.whenReady
                    .then(() => debug.createOGC3DTilesDebugUI(gui, view, window.layer));
            }

            function loadLyon() {
                setUrl("https://raw.githubusercontent.com/iTowns/iTowns2-sample-data/refs/heads/master/3DTiles/lyon1-4978/tileset.json");
            }

            function loadSete() {
                setUrl("https://raw.githubusercontent.com/iTowns/iTowns2-sample-data/master/pointclouds/pnts-sete-2021-0756_6256/tileset.json");
            }

            function loadLille() {
                setUrl("https://webimaging.lillemetropole.fr/externe/maillage/2020_mel_5cm/tileset.json");
            }

            window.readURL = readURL;
            window.loadLyon = loadLyon;
            window.loadSete = loadSete;
            window.loadLille = loadLille;

        </script>
    </body>
</html>
